/**
 * \file PluginObject_Win32.h
 * \brief Plugin declaration class for Windows platforms
 * \author Edouard ROGE
 * \date 16 March 2013
 */
#ifndef _PLUGINOBJECT_WIN32_
#define _PLUGINOBJECT_WIN32_


#include "Plugin.h"

/**
 * \class PluginObject
 * \brief Base class for every plug-in
 */
template<typename T>
class PluginObject : public Plugin
{
public:

	/**
	 * \fn PluginObject()
	 * \brief Default constructor
	 */
	PluginObject() :Plugin()
	{
	}

	/**
	 * \fn virtual ~PluginObject()
	 * \brief Destructor
	 */
	virtual ~PluginObject()
	{
	}
	
	/**
	 * \fn error Load(const String & _strPluginName)
	 * \param _strPluginName name of the plug-in to load
	 * \return an error if occurs
	 * \brief Load a Plugin
	 */
	virtual error Load(const String & _strPluginName)
	{
		m_hLibrary = ::LoadLibrary(_strPluginName.GetData());
		if ( !m_hLibrary )
		{
			//LOG_ERROR("Couldn't find "<<_PluginName<<" plugin");
			return errFailed;
		}

		LOADINGFUNCTION pLoadingFunc = (LOADINGFUNCTION)::GetProcAddress( m_hLibrary, "DLLEntry" );
		if ( !pLoadingFunc )
		{
			//LOG_ERROR("Couldn't find "<<_PluginName<<" plugin");
			return errFailed;
		}

		m_pInterface = pLoadingFunc();

		if(!m_pInterface)
		{
			Unload();
			//LOG_ERROR("Couldn't find "<<_PluginName<<" plugin");
			return errFailed;
		}

		return errOK;
	}

	/**
	 * \fn error Unload()
	 * \return an error if occurs
	 * \brief Unload a Plugin
	 */
	virtual error Unload()
	{
		::FreeLibrary(m_hLibrary);

		if(m_pInterface)
		{
			delete m_pInterface;
			m_pInterface=NULL;
		}

		return errOK;
	}
	
private:

	/** Handle to the loaded plug-in */
	HANDLE m_hLibrary;

	typedef T* (*LOADINGFUNCTION)();
};

#endif // _PLUGINOBJECT_WIN32_
